# -*- coding:utf-8 -*-
import json
import traceback
import time

import requests

from urllib.parse import unquote_plus


def check_configuration(context):
    iam_domain = context.getUserData('iam_domain')
    iam_user = context.getUserData('iam_user')
    iam_password = context.getUserData('iam_password')
    if not iam_domain:
        return 'IAMDomain is not configured'
    if not iam_user:
        return 'IAMUser is not configured'
    if not iam_password:
        return 'IAMPassword is not configured'
    ak = context.getAccessKey().strip()
    sk = context.getSecretKey().strip()
    if not ak or not sk:
        ak = context.getUserData('ak', '').strip()
        sk = context.getUserData('sk', '').strip()
        if not ak or not sk:
            return 'ak or sk is empty'


class Processor:

    def __init__(self, context):
        self.log = context.getLogger()
        self.obs_client = None
        self.obs_bucket_name = None
        self.obs_object_key = None
        self.obs_apk_path = None
        self.output_object_key = None
        self.result_bucket = context.getUserData('result_bucket')
        self.iam_domain = context.getUserData('iam_domain')
        self.iam_user = context.getUserData('iam_user')
        self.iam_password = context.getUserData('iam_password')
        self.region = None
        self.endpoint = None
        self.project_id = None

    def get_region(self, record):
        if 'eventRegion' in record:
            self.region = record.get("eventRegion")
        else:
            self.region = record.get("awsRegion")

    def get_endpoint(self):
        self.endpoint = "cph." + f"{self.region}" + ".myhuaweicloud.com"

    def get_iam_token(self):
        """获取IAM用户token"""
        url = "https://iam.myhuaweicloud.com/v3/auth/tokens?nocatalog=true"
        headers = {
            "Content-Type": "application/json;charset=utf8"
        }
        params = {
            "auth": {
                "identity": {
                    "methods": [
                        "password"
                    ],
                    "password": {
                        "user": {
                            "domain": {
                                "name": self.iam_domain
                            },
                            "name": self.iam_user,
                            "password": self.iam_password
                        }
                    }
                },
                "scope": {
                    "project": {
                        "name": self.region
                    }
                }
            }
        }

        response = requests.post(url=url, headers=headers, data=json.dumps(params))
        token = response.headers["X-Subject-Token"]
        return token

    def get_project_id(self, token):
        """获取region的project_id"""
        url = f"https://iam.myhuaweicloud.com/v3/projects"
        params = {
            "name": self.region
        }
        headers = {
            "Content-Type": "application/json;charset=utf8",
            "X-auth-Token": token
        }
        response = requests.get(url=url, params=params, headers=headers)
        response_body = json.loads(response.text)
        self.project_id = response_body["projects"][0]["id"]

    def get_phone_id(self, token):
        """获取云手机实例id"""
        url = f"https://{self.endpoint}/v1/{self.project_id}/cloud-phone/phones"
        headers = {
            "Content-Type": "application/json",
            "X-Auth-Token": token
        }
        resp = requests.get(url=url, headers=headers)
        resp_json = json.loads(resp.text)

        phone_ids = list()
        for ph in resp_json["phones"]:
            phone_id = ph["phone_id"]
            phone_ids.append(phone_id)
        return phone_ids

    def give_app_required_permission(self, phone_ids, token):
        """自动对app授权"""
        url = f"https://{self.endpoint}/v1/{self.project_id}/cloud-phone/phones/batch-update-property"
        headers = {
            "X-Auth-Token": token
        }
        phone_property = '{"ro.permission.changed":"1", "ro.install.auto": "1"}'
        request_body = {"phones": []}
        for ph in phone_ids:
            request_body["phones"].append({"phone_id": ph, "property": phone_property})
        resp = requests.post(url=url, headers=headers, data=json.dumps(request_body))
        time.sleep(200)
        return resp.text

    def install_app(self, token, obs_apk_path, phone_ids):
        """在云手机中安装apk"""
        headers = {
            "X-Auth-Token": token
        }
        url = f"https://{self.endpoint}/v1/{self.project_id}/cloud-phone/phones/commands"
        params = {
            "command": "install",
            "content": f"-t -r {obs_apk_path}",
            "phone_ids": phone_ids
        }
        response = requests.post(url=url, headers=headers, data=json.dumps(params))
        return response

    def save_result(self, result):
        try:
            resp = self.obs_client.putContent(self.result_bucket,
                                              self.output_object_key,
                                              content=result)
            if resp.status < 300:
                self.log.info("succeed to save response")
            else:
                self.log.error("failed to save response, "
                               f"requestId: {resp.requestId} "
                               f"errorCode: {resp.errorCode} "
                               f"errorMessage: {resp.errorMessage}")
        except Exception as e:
            e = traceback.format_exc(e)
            self.log.error("failed to save response, "
                           f"exception: {e}")

    def analysis_record(self, record):
        # 提取apk文件所在的obs桶和key
        bucket_name, object_key = self.get_obs_obj_info(record)
        self.obs_bucket_name = bucket_name
        self.log.info("input bucket_name: %s", bucket_name)
        self.obs_object_key = unquote_plus(object_key)
        self.log.info("input object: %s", self.obs_object_key)
        # 拼接apk文件obs路径
        self.obs_apk_path = "obs://{0}/{1}".format(self.obs_bucket_name, self.obs_object_key)

    def process(self, record):
        self.get_region(record)
        self.get_endpoint()
        token = self.get_iam_token()
        self.get_project_id(token)
        self.analysis_record(record)
        phone_ids = self.get_phone_id(token)
        self.give_app_required_permission(phone_ids, token)
        time.sleep(150)  # 云手机属性变更等待生效
        self.log.info(self.iam_domain + "," + self.region + "," + self.endpoint + "," + token + "," + self.project_id)
        self.install_app(token, self.obs_apk_path, phone_ids)

    @staticmethod
    def get_obs_obj_info(record):
        if 's3' in record:
            s3 = record['s3']
            return s3['bucket']['name'], s3['object']['key']
        else:
            return "", ""


def handler(event, context):
    """函数工作流入口"""
    log = context.getLogger()
    result = check_configuration(context)
    if result is not None:
        return result

    records = event.get("Records", None)
    if records is None:
        return 'Records is empty'

    processor = Processor(context)
    try:
        for record in records:
            processor.process(record)
    except Exception as e:
        log.error(e)
        e = traceback.format_exc(e)
        log.error("failed to process obs, "
                  f"exception：{e}")
    return 'Done'
